#pragma once

#include <memory>

#include "Socket.hpp"
#include "nocopy.hpp"
#include "threadpool.hpp"

template <class T>
struct ThreadData
{
    ThreadData()
        : _sk(nullptr)
        , _task(T())
    {}
    ThreadData(Socket* sk, T task)
        : _sk(sk)
        , _task(task)
    {}
    const ThreadData<T>& operator=(const ThreadData<T> another)
    {
        if(this != &another)
        {
        _sk = another._sk;
        _task = another._task;
        }
        return *this;
    }
    Socket* _sk;
    T _task;
};

template <class T>
class Server : public nocopy
{
public:
    //在创建Server的时候，直接完成定义，并且拿到Server的thread要执行的函数方法
    Server(in_port_t port, T task)
        : _server_usage(new ServerSocket(port)), _task(task)
    {
        _server_usage->ServerInit();
    }

    //启动server
    //1. 让主线程进行获取连接，并向线程池中push方法，激活线程池的某一个线程
    //2. 让线程池的线程去拿到执行的方法
    void Running()
    {
        // 先将线程池的线程分离，无需让主线程进行回收，主线程专心获取连接、并push激活线程池的线程即可
        ThreadPool<ThreadData<T>>::GetOnce()->Detach_Threads();

        // 启动线程
        ThreadPool<ThreadData<T>>::GetOnce()->Start_Task();

        while (true)
        {
            ThreadData<T> td(_server_usage.get(), _task);

            // 主线程一直去获取连接
            _server_usage->SocketAccept(); //获取失败直接退出，成功就往下，没有可以获取的就阻塞

            // 【获取成功】push 任务 到线程池中，让线程池的线程进行处理
            ThreadPool<ThreadData<T>>::GetOnce()->Push(td);
        }
    }

private:
    std::shared_ptr<Socket> _server_usage;
    T _task;
};